/* An example showing the usage of generik::threads

It describes a typical producer-consumer problem, typically
solved using coroutines.
In this case, the consumer's role is filled by a pool of 
threads, and the producer is a seperate thread.

Communication between the two groups is performed via an
input/output object, which uses two conditions to signal
whether data is available or not.

As such the two classes are virtual mirrors of each other.

The only simplification in this example is that the producer
does not actually restock the input data with new data,
but instead terminates the program. It would not be very 
hard to modify it to do this, however.


*/
#include <generik/tracing.h>
GENERIK_TRACER_GLOBAL

#include <generik/threadpool.h>

struct intdata
: generik::threadsyncdata<int, int>
{
	intdata(int n)
	{
		GENERIK_TRACER;
		for (int i = 0; i < n; ++i)
		{
			_inbox.push_back(i);
		}
	}
	
	int process(int& in)
	{
		GENERIK_TRACER;
		return in * 2;
	}
	
	bool refill()
	{
		return false;
	}
};

#include <fstream>

/*
read all the lines into an input std::list<std::string> buffer
process each line using the inputdata = process(line) method.
(this should convert date-time fields into integer seconds, ie. Unix time)
when all is done, sort according to this time field.
so we have as output a std::list<inputdata*> list
Process this list, copy each griddata field into the griddata array, thereafter freeing the memory
*/

int main(int argc, char** argv)
{
	GENERIK_TRACER;
	
	intdata _data(10);
	
	generik::threadpool<generik::processthread> _threads(2, _data);
	generik::fillthread _fillthread(_data);
	// the order of these two calls do not really matter
	_threads.execute();
	_fillthread.execute();
	GENERIK_TRACE("waiting");
	_fillthread.join(); // this blocks until _fillthread is done
	_threads.stop();
	
	// so after threadpool is finalised, we'll have
	// _data.execute()
	
	GENERIK_FOR_EACH(i, _data._outbox)
	{
		std::cerr<<(*i)<<std::endl;
	}
	
	return 0;
}





